package zhihui.mobile.app;

import android.content.Context;
import android.os.Looper;
import android.os.Process;
import android.util.Log;
import android.widget.Toast;

import com.zgm.utils.DeviceUtils;
import com.zgm.utils.FileUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
 * Created by 张公铭 on 2017/6/19 0019.
 * 全局异常捕获类
 */

public class CrashHandler implements Thread.UncaughtExceptionHandler
{
    private static CrashHandler crashHandler;
    //默认的UncauhgException处理类
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    //异常信息
    private Map<String, String> crashMap = new HashMap<String, String>();
    //日期格式
    private DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
    private Context mContext;
    private String saveDir;

    private CrashHandler()
    {

    }

    private static synchronized void createdIns()
    {
        if (crashHandler == null)
        {
            crashHandler = new CrashHandler();
        }
    }

    public static CrashHandler getInstance()
    {
        if (crashHandler == null)
        {
            createdIns();
        }
        return crashHandler;
    }

    /**
     * 初始化异常捕获处理器
     */
    public void init(Context context, String dir)
    {
        mContext = context;
        saveDir = dir;
        //获取系统默认的异常捕获处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        //设置本类为程序默认的处理器
//        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 异常捕获处理方法
     */
    @Override
    public void uncaughtException(Thread t, Throwable e)
    {
        Log.d("CrashHandler", t.toString() + "-----" + e.toString());
        if (!handleException(e) && mDefaultHandler != null)
        {
            mDefaultHandler.uncaughtException(t, e);
        } else
        {
            Log.d("CrashHandler", "close");
            try
            {
                Thread.sleep(3000);
            } catch (InterruptedException e1)
            {
                Log.e("CrashHanlder", "sleep error", e1);
            }
            MyApplication.appExit();
            Process.killProcess(Process.myPid());
            System.exit(0);
        }
    }

    public boolean handleException(Throwable ex)
    {
        if (ex == null)
        {
            Log.d("CrashHandler", false+"");
            return false;
        } else
        {
            (new Thread()
            {
                @Override
                public void run()
                {
                    Looper.prepare();
                    Toast.makeText(CrashHandler.this.mContext, "很抱歉，程序异常，即将退出！", Toast.LENGTH_LONG).show();
                    Looper.loop();
                }
            }).start();
            crashMap.putAll(DeviceUtils.collectDeviceInfo(mContext));
            saveCrashInfoToFile(ex);
            Log.d("CrashHandler", true+"");
            return true;
        }
    }

    private void saveCrashInfoToFile(Throwable ex)
    {
        StringBuffer sb = new StringBuffer();
        Iterator iterator = crashMap.entrySet().iterator();

        String result;
        while (iterator.hasNext())
        {
            Map.Entry writer = (Map.Entry) iterator.next();
            String cause = (String) writer.getKey();
            result = (String) writer.getValue();
            sb.append(cause + "=" + result + "\n");
        }

        StringWriter writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);

        for (Throwable cause = ex.getCause(); cause != null; cause = cause.getCause())
        {
            cause.printStackTrace(printWriter);
        }
        printWriter.close();
        result = writer.toString();
        sb.append(result);
        try
        {
            String time = dateFormat.format(new Date());
            String fileName = "crash-" + time + ".log";
            File file = FileUtils.createNewFile(saveDir + fileName);
            FileOutputStream out = new FileOutputStream(file);
            out.write(sb.toString().getBytes());
            out.close();
        } catch (FileNotFoundException e)
        {
            Log.e("CrashHandler", "saveCrashToFile error", e);
        } catch (IOException e)
        {
            Log.e("CrashHandler", "saveCrashToFile error", e);
        }
    }
}
